16-2 Session

Application 物件可讓同一個 Web 應用程式共用資訊,而 Session 物件可讓同一個使用者在不同的 Web 應用程式中共用資訊。換句話說,同一個使用者在不同的 Request 中,可用 Session 物件來保存資訊,而其保存資訊的方法,則是靠 Cookies 來達成。因此,要能夠使用 Session 物件的首要條件,就是用戶端的 Cookies 功能必須是開啟的。

Session 物件提供四種性質(Properties)、一種方法(Method)、兩個事件(Events)與兩個集合(Collections),列表如下:

Session 物件的性質
性質說明
CodePage語言識別碼(例:950代表繁體中文、936代表簡體中文、65001代表UTF-8)
LCID地區識別碼(例:1028代表台灣地區、3076代表香港地區、2052代表大陸地區)
SessionID用戶端的 SessionID
TimeoutSession 物件的有效時間(以分鐘為單位),預設為20分鐘

Session 物件提供的方法
方法說明
Abandon刪除 Session 物件所含的所有資訊
Contents.Remove(item or index)刪除 Contents 集合中的某一個項目
Contents.RemoveAll刪除 Contents 集合中的所有項目

Session 物件提供的事件
事件說明
OnStart啟動一個 Session 物件時所觸發的函式,此函式必須放在 global.asa 檔案
OnEnd結束一個 Session 物件時所觸發的函式,此函式必須放在 global.asa 檔案

Session 物件提供的集合
集合說明
Contents所有加在 Session 物件的變數集合
StaticObjects所有在使用者層級(Session Scope)所宣告的物件集合

當使用者點選某一個網頁時,伺服器就會對此使用者分配一個 session ID,並以 cookie 的方式記錄在用戶端。此 session ID 的有效期間是 20 分鐘,這些資訊都可由下列網頁來呈現:

Example(session/sessionId01.asp):

在上述範例中,Session.CodePage=950代表用戶端的預設語言是繁體中文(大五碼),Session.LCID=1028代表用戶端所在的區域是台灣地區,此範例的原始檔如下:

原始檔(session/sessionId01.asp):(灰色區域按兩下即可拷貝)
<%@language=JScript%>
<%title="顯示 Session.SessionID 及 Session.Timeout "%>
<!--#include file="../head.inc"-->
<hr>

<p>
Your session ID is <b><font color=green><%=Session.SessionID%></font></b>, which will be changed in
<b><font color=green><%=Session.Timeout%></font></b> minutes when you access this page again.
<p>
All session info:
	<ul>
	<li>Session.SessionID = <font color=green><%=Session.SessionID%></font>
	<li>Session.Timeout = <font color=green><%=Session.Timeout%></font>
	<li>Session.CodePage = <font color=green><%=Session.CodePage%></font>
	<li>Session.LCID = <font color=green><%=Session.LCID%></font>
	</ul>
<hr>
<!--#include file="../foot.inc"-->

由於 Session 物件是用來指定每一個使用者的相關資訊,因此我們可以根據使用者的語言或地區的不同,來顯示不同的資訊。例如 Session.LCID 是用來指定區域代碼,根據不同的區域代碼,我們就可以產生不同的日期字串,範例如下:

Example(session/sessionLcid01.asp):

上述範例的原始檔如下:

原始檔(session/sessionLcid01.asp):(灰色區域按兩下即可拷貝)
<%@language=JScript%>
<%title="經由改變 Session.LCID 來改變日期格式"%>
<!--#include file="../head.inc"-->
<hr>

<%
today=new Date();
currentLcid=Session.LCID;	// 記錄目前的 LCID
Session.LCID=1028;
Response.write("台灣:LCID="+Session.LCID + ", 當地日期字串="+today.toLocaleString());
Session.LCID=1041;
Response.write("<br>日本:LCID="+Session.LCID + ", 當地日期字串="+today.toLocaleString());
Session.LCID=1036;
Response.write("<br>法國:LCID="+Session.LCID + ", 當地日期字串="+today.toLocaleString());
Session.LCID=1031;
Response.write("<br>德國:LCID="+Session.LCID + ", 當地日期字串="+today.toLocaleString());
Session.LCID=2057;
Response.write("<br>英國:LCID="+Session.LCID + ", 當地日期字串="+today.toLocaleString());
Session.LCID=currentLcid;	// 改回原來的 LCID
%>

<hr>
<!--#include file="../foot.inc"-->

Hint
在上述範例中,你必須將 Session.LCID 設定回原來的預設值,否則與地區相關的顯示(如日期等)就會發生錯誤。

Session 和 Application 物件一樣,都有 OnStart 和 OnEnd 兩個事件,這兩個事件對應的函式是 Session_OnStart() 和 Session_OnEnd(),也都必須存放在 global.asa 檔案中。若 Application 和 Session 同時啟動,ASP 會先執行 Application_OnStart(),再執行 Session_OnStart()。若兩者同時結束,ASP 會先執行 Session_OnEnd(),再執行 Application_OnEnd()。這些執行順序可列出如下:

  1. Application_OnStart()
  2. Session_OnStart()
  3. ASP scripts
  4. Session_OnEnd()
  5. Application_OnEnd()

以下我們將使用「加強版的訪客計數器」,來說明如何使用 Session 及 Application 物件,使得用戶端在點選「重新整理」時,計數器的值不會一再累加。

其方法可說明如下:在被計數的網頁 ASP 程式碼中,檢查 Session("PreviouslyOnLine") 的值,若是 true,則不做任何事。若是 false,則將其值改為 true,並將 Application("Counter") 的值加一。換句話說,只要每次有人瀏覽此網頁,而且 Session("PreviouslyOnLine") 的值是 false,Application("Counter") 的值就會加一,其值即代表此網頁被點選的次數,它並不會因為使用者在短期(20分鐘)內點選「重新整理」而盲目增加。請見以下範例:

Example(session/pagehit01.asp):

上述範例的原始檔如下:

原始檔(session/pagehit01.asp):(灰色區域按兩下即可拷貝)
<%@language=JScript%>
<%title="使用 Application 與 Session 物件來防止計數資料的竄改:方法一"%>
<!--#include file="../head.inc"-->
<hr>

<%
if (Application("Counter")==null)
	Application("Counter") = 0;	//在 JScript,預設值不是 0
if (Session("PreviouslyOnLine")!=true){
	Application("Counter")++;
	Session("PreviouslyOnLine") = true;
}
%>
<h3 align=center>您是第 <font color=red><%=Application("Counter")%></font> 位貴賓!</h3>

<hr>
<!--#include file="../foot.inc"-->

此外,我們可以再加上「獨立計數」、「計數器啟用時間」等功能,得到一個較完整的範例:

Example(session/pagehit02.asp):

上述範例的原始檔如下:

原始檔(session/pagehit02.asp):(灰色區域按兩下即可拷貝)
<%@language=JScript%>
<%title="使用 Application 與 Session 物件來防止計數資料的竄改:方法二"%>
<!--#include file="../head.inc"-->
<hr>

<%
//Application.Contents.Removeall();	// 清除變數以便測試此網頁
//Session.Contents.Removeall();		// 清除變數以便測試此網頁
url = Request.ServerVariables("URL");
startTime = "Start time of "+url;
if (Application(startTime)==null){	// 啟始變數及時間
	Application(url)=0;		// 開始計數
	now = new Date();
	Application(startTime)=now.toLocaleString();
}
if (Session(url)==null){	// Session(url) 不存在
	Application(url)++;
	Session(url)=true;
} else {%>
	<script>alert("你想竄改計數器?沒那麼容易喔!");</script>
<%}%>
<h3 align=center>從 <font color=green><%=Application(startTime)%></font> 以來,您是第 <font color=red><%=Application(url)%></font> 位貴賓!</h3>

<hr>
<!--#include file="../foot.inc"-->

上述記數器範例雖然有許多功能,但仍有一個缺點:伺服器重開機時,Application 物件會被清除,因此所有的計數資料就不見了,一切歸零。要解決這個問題,則要將計數資料寫入檔案,後面再詳細介紹。

我們也可以每隔一天,就將記數器的資料寫入檔案,這樣的好處是:

範例如下:

Example(session/pagehit03.asp):

上述範例的原始檔如下:

原始檔(session/pagehit03.asp):(灰色區域按兩下即可拷貝)
<%@language=JScript%>
<%title="記錄每日來訪人數"%>
<!--#include file="../head.inc"-->
<hr>

<%
// 下列程式碼可以將每天訪客的人數(含頁次和人次)記錄於 counter.txt
// Application.Contents.RemoveAll();		// 清除變數以便測試此網頁
// Session.Contents.RemoveAll();		// 清除變數以便測試此網頁
if (Application("counterDate")==null){
	Application("counter1") = 0;
	Application("counter2") = 0;
	today=new Date();
	Application("counterDate") = today.getDate();
	Application("lastRecordTime") = today.toLocaleString();
}

Application("counter1")++;		// 更新頁次計數
if (Session("onlineAlready")!=true){
	Application("counter2")++;	// 更新人次計數
	Session("onlineAlready") = true;
}

// Write to a file if necessary
fso = new ActiveXObject("Scripting.FileSystemObject");
today=new Date();
counterFile="counter.txt";
if (today.getDate()!=Application("counterDate")){		// 若不在同一天,則將資料寫入檔案
	fid = fso.OpenTextFile(Server.MapPath(counterFile), 8, true);	// 8 代表附加資料於檔案,true 代表若無檔案則新增
	fid.WriteLine(today.toLocaleString());
	fid.WriteLine("頁次:"+Application("counter1"));
	fid.WriteLine("人次:"+Application("counter2"));
	fid.Close();
	Application("counter1")=0;
	Application("counter2")=0;
	Application("counterDate")=today.getDate();;
	Application("lastRecordTime")=today.toLocaleString();
}
%>

<h3 align=center>從 <font color=green><%=Application("lastRecordTime")%></font> 以來,
本頁被造訪 <font color=red><%=Application("counter1")%></font> 次,
而您是第 <font color=red><%=Application("counter2")%></font> 位貴賓!</h3>

<hr>
<!--#include file="../foot.inc"-->

而本範例所用來儲存計數資料的檔案可列出如下:

2004年12月31日 下午 09:57:26 頁次:1 人次:1 2004年12月31日 下午 09:57:27 頁次:1 人次:12005年1月1日 上午 12:22:36 頁次:18 人次:1 2005年11月21日 上午 07:42:34 頁次:1 人次:0 2006年11月22日 上午 09:07:44 頁次:1 人次:0 2018年4月4日 上午 01:21:52 頁次:3 人次:3 2018年4月7日 上午 03:08:00 頁次:3 人次:3 2018年4月16日 上午 08:52:26 頁次:3 人次:3 2018年4月21日 上午 09:52:56 頁次:2 人次:2 2018年4月27日 上午 09:03:21 頁次:2 人次:2 2018年5月10日 上午 12:39:10 頁次:4 人次:2 2018年5月15日 下午 07:23:59 頁次:2 人次:2 2018年5月26日 上午 02:07:33 頁次:3 人次:2 2018年6月18日 上午 09:49:13 頁次:3 人次:3 2018年6月19日 上午 11:41:02 頁次:4 人次:4 2018年7月31日 上午 01:51:48 頁次:2 人次:2 2018年8月27日 上午 10:15:04 頁次:3 人次:3 2018年9月4日 上午 02:59:16 頁次:3 人次:3 2018年9月8日 上午 02:58:06 頁次:2 人次:2 2018年9月19日 上午 10:06:29 頁次:2 人次:2 2018年9月22日 上午 02:56:56 頁次:2 人次:2 2018年10月2日 上午 11:05:40 頁次:2 人次:2 2018年10月7日 上午 12:42:38 頁次:2 人次:2 2018年10月11日 上午 10:22:22 頁次:2 人次:2 2018年10月19日 上午 05:11:05 頁次:2 人次:2 2018年10月22日 上午 12:19:59 頁次:2 人次:2 2018年11月1日 上午 09:11:34 頁次:2 人次:2 2018年11月11日 上午 01:49:08 頁次:3 人次:3 2018年11月13日 上午 02:57:14 頁次:2 人次:2 2018年11月22日 上午 12:55:53 頁次:7 人次:2 2018年11月30日 上午 03:18:07 頁次:2 人次:2 2018年12月1日 上午 09:29:44 頁次:2 人次:2 2018年12月12日 上午 10:34:07 頁次:2 人次:2 2018年12月15日 下午 12:44:13 頁次:2 人次:2 2018年12月20日 上午 02:35:50 頁次:8 人次:8 2018年12月30日 上午 12:04:19 頁次:2 人次:2 2019年1月3日 上午 08:54:46 頁次:3 人次:3 2019年1月15日 上午 12:29:05 頁次:2 人次:2 2019年1月25日 上午 04:36:06 頁次:2 人次:2 2019年2月2日 上午 07:40:28 頁次:3 人次:3 2019年3月3日 下午 01:53:03 頁次:2 人次:2 2019年3月4日 上午 06:16:55 頁次:2 人次:2 2019年3月13日 上午 06:12:16 頁次:4 人次:4 2019年3月20日 下午 03:11:56 頁次:2 人次:2 2019年3月31日 下午 01:54:32 頁次:3 人次:3 2019年4月2日 下午 02:25:44 頁次:3 人次:3 2019年4月3日 上午 05:55:53 頁次:2 人次:2 2019年4月12日 上午 04:33:48 頁次:5 人次:5 2019年4月13日 上午 11:03:34 頁次:2 人次:2 2019年5月5日 上午 07:22:58 頁次:2 人次:2 2019年5月15日 上午 09:21:09 頁次:3 人次:3 2019年5月19日 上午 01:08:28 頁次:2 人次:2 2019年5月20日 上午 11:27:40 頁次:2 人次:2 2019年6月3日 下午 12:39:55 頁次:2 人次:2 2019年6月12日 上午 12:39:38 頁次:2 人次:2 2019年6月18日 上午 08:40:37 頁次:2 人次:2 2019年7月11日 下午 02:26:14 頁次:2 人次:2 2019年7月23日 上午 12:17:44 頁次:2 人次:2 2019年7月24日 上午 07:10:07 頁次:5 人次:5 2019年7月29日 上午 03:20:22 頁次:2 人次:2 2019年7月31日 上午 03:27:32 頁次:2 人次:2 2019年8月9日 上午 09:25:27 頁次:2 人次:2 2019年8月10日 上午 10:39:16 頁次:2 人次:2 2019年8月25日 上午 11:27:41 頁次:2 人次:2 2019年9月3日 上午 01:02:54 頁次:6 人次:6 2019年9月14日 上午 06:52:36 頁次:4 人次:4 2019年10月3日 下午 04:49:00 頁次:2 人次:2 2019年10月13日 下午 02:16:44 頁次:2 人次:2 2019年10月18日 下午 12:07:16 頁次:3 人次:3 2019年11月11日 上午 06:14:35 頁次:2 人次:2 2019年11月23日 上午 09:34:11 頁次:2 人次:2 2019年12月22日 上午 01:46:58 頁次:2 人次:2 2020年1月3日 上午 11:50:00 頁次:2 人次:2 2020年1月14日 下午 05:09:22 頁次:2 人次:2 2020年1月16日 下午 04:55:18 頁次:2 人次:2 2020年1月22日 下午 02:26:24 頁次:2 人次:2 2020年1月26日 上午 06:26:09 頁次:3 人次:3 2020年2月4日 上午 09:27:32 頁次:2 人次:2 2020年2月5日 上午 12:33:18 頁次:1 人次:1 2020年3月11日 上午 11:27:35 頁次:2 人次:2 2020年4月11日 下午 02:11:02 頁次:3 人次:3 2020年5月7日 上午 12:00:08 頁次:2 人次:2 2020年5月22日 上午 04:37:41 頁次:2 人次:2 2020年5月24日 下午 12:12:25 頁次:3 人次:3 2020年6月6日 上午 08:08:42 頁次:2 人次:2 2020年6月11日 上午 03:12:48 頁次:2 人次:2 2020年6月15日 上午 09:47:34 頁次:2 人次:2 2020年6月16日 上午 09:51:51 頁次:2 人次:2 2020年6月21日 上午 02:13:49 頁次:2 人次:2 2020年6月30日 上午 12:11:53 頁次:2 人次:2 2020年7月1日 上午 03:25:21 頁次:3 人次:3 2020年7月5日 上午 12:12:03 頁次:2 人次:2 2020年8月31日 上午 04:28:20 頁次:2 人次:2 2020年9月6日 上午 05:14:15 頁次:3 人次:3 2020年10月18日 上午 05:13:55 頁次:4 人次:4 2020年11月2日 上午 04:06:25 頁次:2 人次:2 2020年11月5日 下午 12:03:02 頁次:4 人次:4 2020年11月6日 下午 08:34:28 頁次:2 人次:2 2020年11月9日 上午 09:59:27 頁次:2 人次:2 2020年11月20日 上午 12:04:22 頁次:2 人次:2 2020年12月3日 上午 10:44:25 頁次:4 人次:4 2021年1月4日 上午 07:57:51 頁次:4 人次:4 2021年1月19日 上午 05:25:32 頁次:2 人次:2 2021年1月21日 上午 11:38:15 頁次:2 人次:2 2021年3月3日 上午 04:37:52 頁次:2 人次:2 2021年3月16日 上午 03:18:03 頁次:3 人次:3 2021年3月19日 上午 05:56:51 頁次:2 人次:2 2021年3月23日 上午 05:44:47 頁次:3 人次:3 2021年4月4日 上午 01:43:16 頁次:2 人次:2 2021年4月10日 上午 09:49:00 頁次:3 人次:3 2021年4月14日 上午 01:38:55 頁次:5 人次:2 2021年4月25日 上午 03:11:10 頁次:3 人次:3 2021年5月18日 上午 02:46:32 頁次:3 人次:3 2021年5月23日 下午 12:36:55 頁次:2 人次:2 2021年5月24日 上午 09:11:13 頁次:2 人次:2 2021年6月12日 上午 12:19:08 頁次:2 人次:2 2021年6月15日 上午 01:28:34 頁次:2 人次:2 2021年6月22日 上午 12:16:00 頁次:2 人次:2 2021年6月28日 上午 09:12:37 頁次:5 人次:5 2021年7月6日 上午 07:01:29 頁次:2 人次:2 2021年7月15日 上午 10:01:37 頁次:2 人次:2 2021年7月31日 上午 03:10:50 頁次:2 人次:2 2021年8月7日 上午 07:55:05 頁次:3 人次:3 2021年8月13日 上午 08:16:07 頁次:2 人次:2 2021年8月25日 上午 05:14:38 頁次:3 人次:3 2021年9月9日 上午 12:24:46 頁次:2 人次:2 2021年9月20日 上午 06:40:49 頁次:2 人次:2 2021年9月27日 下午 01:48:38 頁次:2 人次:2 2021年10月27日 上午 12:39:19 頁次:2 人次:2 2021年12月4日 上午 04:22:31 頁次:2 人次:2 2021年12月7日 上午 01:03:27 頁次:2 人次:2 2021年12月9日 下午 04:05:51 頁次:2 人次:2 2021年12月15日 上午 12:07:29 頁次:2 人次:2 2021年12月16日 上午 07:00:55 頁次:4 人次:4 2022年1月1日 上午 10:40:01 頁次:2 人次:2 2022年1月6日 上午 02:55:59 頁次:2 人次:2 2022年1月7日 上午 07:58:14 頁次:5 人次:5 2022年1月19日 上午 11:12:22 頁次:2 人次:2 2022年2月8日 上午 02:41:52 頁次:2 人次:2 2022年2月13日 上午 01:54:24 頁次:2 人次:2 2022年3月15日 上午 03:41:47 頁次:2 人次:2 2022年4月10日 上午 12:00:27 頁次:2 人次:2 2022年4月13日 上午 01:55:25 頁次:2 人次:2 2022年4月14日 下午 04:59:52 頁次:2 人次:2 2022年4月23日 上午 01:21:39 頁次:2 人次:2 2022年5月16日 上午 05:06:01 頁次:2 人次:2 2022年5月17日 上午 09:31:56 頁次:2 人次:2 2022年6月15日 上午 02:41:41 頁次:2 人次:2 2022年6月16日 下午 12:18:03 頁次:2 人次:2 2022年6月29日 上午 07:02:44 頁次:2 人次:2 2022年7月1日 上午 03:14:58 頁次:2 人次:2 2022年7月3日 上午 02:32:45 頁次:2 人次:2 2022年7月6日 上午 07:38:46 頁次:2 人次:2 2022年9月2日 上午 05:25:02 頁次:2 人次:2 2022年9月13日 上午 11:08:24 頁次:2 人次:2 2022年10月28日 下午 04:20:13 頁次:2 人次:2 2022年11月1日 上午 01:18:07 頁次:2 人次:2 2022年11月16日 下午 04:02:56 頁次:2 人次:2 2022年12月8日 上午 06:30:26 頁次:2 人次:2 2022年12月13日 上午 09:06:39 頁次:3 人次:3 2023年1月3日 上午 12:46:59 頁次:2 人次:2 2023年1月14日 上午 12:39:05 頁次:2 人次:2 2023年1月16日 下午 02:01:15 頁次:2 人次:2 2023年2月8日 上午 09:31:04 頁次:4 人次:4 2023年2月13日 上午 08:51:48 頁次:2 人次:2 2023年2月24日 上午 03:32:04 頁次:2 人次:2 2023年3月17日 上午 03:33:06 頁次:2 人次:2 2023年4月8日 上午 05:06:46 頁次:2 人次:2 2023年4月18日 上午 03:37:54 頁次:3 人次:3 2023年6月30日 上午 02:04:31 頁次:2 人次:2 2023年7月22日 上午 02:42:04 頁次:2 人次:2 2023年9月2日 上午 07:53:28 頁次:2 人次:2 2023年9月13日 下午 04:29:47 頁次:2 人次:2 2023年11月9日 上午 11:54:58 頁次:2 人次:2 2023年11月12日 上午 06:27:57 頁次:2 人次:2 2023年12月1日 上午 07:03:11 頁次:3 人次:2 2023年12月9日 上午 08:39:02 頁次:2 人次:2 2024年2月3日 上午 05:15:30 頁次:2 人次:2 2024年2月14日 上午 10:25:45 頁次:2 人次:2 2024年3月5日 上午 02:31:04 頁次:2 人次:2 2024年4月3日 上午 12:25:47 頁次:2 人次:2 2024年4月19日 上午 12:39:22 頁次:2 人次:2 2024年4月23日 上午 05:54:49 頁次:3 人次:3 在上述範例中,我們將計數資料分為「頁次」和「人次」:

Session 物件是一個很好用的保存資訊方法,其他相關應用有:

特別必須注意的是:Session 物件的正常運作必須倚賴用戶端開啟 Cookies 功能,因此如果妳的網頁使用到 Session 物件,最好必須在網頁之前加上測試 Cookies 是否開啟的測試,若未開啟,可提醒使用者開啟 Cookies 以確保網頁正常運作。

Hint
事實上,用戶端的 Cookies 只是用來存放 session ID,而其他與 session 相關的資訊都存放在伺服器,但伺服器必須靠 session ID 才能取得這些資訊。


JScript 程式設計與應用:用於伺服器端的 ASP 環境